<script setup lang="ts">
import Monster from "@/assets/js/monsterClass"
import SpriteImage from "@/components/spriteImage.vue";
import {onMounted, reactive, ref, watch} from "vue";
import {squareMap} from "@/assets/js/squareMap";
import {settings} from "@/settings";
import {useUpdate} from "@/hook/useUpdate";

const personCoordinate = ref({x: 1, y: 1})
const personPosition = ref({
  x: personCoordinate.value.x * settings.width,
  y: personCoordinate.value.y * settings.height
})
const person = ref<InstanceType<typeof SpriteImage> | null>(null)
const firstFloor: any = reactive([
  [{square: 0}, {square: 0}, {square: 0}, {square: 0}, {square: 0}, {square: 0}, {square: 0}, {square: 0}, {square: 0}, {square: 0}, {square: 0}, {square: 0}, {square: 0}],
  [{square: 0}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 0}],
  [{square: 0}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 0}],
  [{square: 0}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 0}],
  [{square: 0}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 0}],
  [{square: 0}, {square: 1}, {square: 1}, {square: 1}, new Monster('greenSlime'), {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 0}],
  [{square: 0}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 0}],
  [{square: 0}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 0}],
  [{square: 0}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 0}],
  [{square: 0}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 0}],
  [{square: 0}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 0}],
  [{square: 0}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 1}, {square: 0}],
  [{square: 0}, {square: 0}, {square: 0}, {square: 0}, {square: 0}, {square: 0}, {square: 0}, {square: 0}, {square: 0}, {square: 0}, {square: 0}, {square: 0}, {square: 0}],
])
const personNameMap: any = {
  'x1': 'personRight',
  'x-1': 'personLeft',
  'y1': 'personBottom',
  'y-1': 'personTop'
}
const personName: any = ref('personBottom')
const moveCollision = (square: any) => {
  return new Promise((resolve, reject) => {
    console.log(square)
    if (square.type === 'monster') {
      square.square = 0
      useUpdate()
      setTimeout(() => {
      //   这里是战斗
        resolve(true)
      },1000)
    }else{
      resolve(true)
    }
  })
}
let moving = false
const personMove = async (status: number) => {
  return new Promise(async (resolve, reject) => {
    if (moving || !isDown) {
      resolve(false)
      return
    }
    const direction = status % 2 === 0 ? 'x' : 'y'
    const mark = status === 1 || status === 4 ? -1 : 1
    const targetCoordinate = {...personCoordinate.value, [direction]: personCoordinate.value[direction] + mark}
    const targetSquare = firstFloor[targetCoordinate.y][targetCoordinate.x]
    if (targetSquare.square === 0) {
      resolve(false)
      return
    }
    await moveCollision(targetSquare)
    // 人物开始移动
    moving = true
    let index = person.value && person.value.movePerson()
    const personAnimation = () => {
      if (index !== 0 && index !== 2) {
        setTimeout(() => {
          index = person.value && person.value.movePerson()
          personAnimation()
        }, settings.personMoveTime / 2)
      }
    }
    personAnimation()
    const speed = settings[direction === 'x' ? 'width' : 'height'] / settings.personMoveTime * 8
    const targetPosition = {
      ...personPosition.value,
      [direction]: personPosition.value[direction] + mark * settings[direction === 'x' ? 'width' : 'height']
    }
    personPosition.value[direction] = personPosition.value[direction] + mark * speed
    personName.value = personNameMap[direction + mark]
    const timer = setInterval(() => {
      personPosition.value[direction] = personPosition.value[direction] + mark * speed
      if ((mark === 1 && personPosition.value[direction] >= targetPosition[direction]) || (mark === -1 && personPosition.value[direction] <= targetPosition[direction])) {
        personPosition.value[direction] = targetPosition[direction]
        personCoordinate.value.x = targetCoordinate.x
        personCoordinate.value.y = targetCoordinate.y
        clearInterval(timer)
        moving = false
        resolve(true)
      }
    }, 8)
  })
}

// 1:向上  2:向右  3:向下  4:向左
// 38 向上 39向右 40向下 37向左
let isDown = false // 方向键是否按下
const dirCodeMap = {38: 1, 39: 2, 40: 3, 37: 4} // 键盘code字典
const pathArr = ref<number[]>([]) //路径点
let keyCode: number = -1 // 按下的keyCode 用于锁定键盘  在未抬起之前  按下其他方向键没有作用
onMounted(()=>{
  window.addEventListener('keydown', async (e) => {
    if (isDown) return
    const status = dirCodeMap[e.keyCode as keyof typeof dirCodeMap]
    keyCode = e.keyCode
    isDown = true
    if (status) {
      pathArr.value.push(status)
      const move = () => {
        personMove(status).then((flag) => {
          flag && move()
        })
      }
      move()
    }
  })
  window.addEventListener('keyup', (e) => {
    if (e.keyCode === keyCode) {
      isDown = false
    }
  })
})
</script>

<template>
  <div class="mota">
    <div v-for="(item,index) in firstFloor" :key="index">
      <template v-for="(item2,index2) in item" :key="index2">
        <sprite-image :name="squareMap[item2.square]"/>
      </template>
    </div>
    <sprite-image ref="person" :style="{left:`calc(${personPosition.x} * 1px)`,top:`calc(${personPosition.y} * 1px)`}" class="person" :name="personName"
    />
  </div>
</template>

<style scoped>
.mota {
  font-size: 0;
  position: relative;
}

.person {
  position: absolute;
}
</style>
